Persistence是一个支持多数据源,O-R映射和SQL映射且简单易用的持久化框架。 最新版本可以满足复杂应用程序开发的需要。 它将帮助开发人员减少花在DAO模块上的开发和维护时间。
新版本的日志工具根据Persistence2.0的需求做了改进,主要特点是:
配置文件内容如下:
//show welcome words welcome=false //print in console debug=true //log folder path logFolderPath=D:/log/ //custom date format //dateFormat=yyyy-MM-dd HH:mm:ss:SSS //log info in single line singleLineLog=true //the min level to show log in console //leve:fatal > error > warn > info > debug minLevel2Print=info //the min level to record log in file minLevel2File=warn
调用方法如下:
Logger logger = Logger.getInstance(); //simple model, no exception logger.debug("[Test]" + info, null); //simple model, has an exception logger.error("[Test]" + info, new Exception("Error.")); //detail model, has an exception LogData data = new LogData(); data.setUser("admin:tom") //Not necessary .setSource("login.jsp") //Not necessary .setCategory("security") //Not necessary .setData("User name : tom . ") //Not necessary .setDescription("Login error."); //Not necessary logger.fatal(data, new Exception("Error."));
数据源工具根据Persistence2.0的需求做了改进,主要变化是使用ThreadLocal管理线程。
连接池配置
<?xml version='1.0' encoding='UTF-8'?> <Context> <DataSource name="mysql" type="javax.sql.DataSource"> <parameter> <name>driverClass</name> <value>com.mysql.jdbc.Driver</value> </parameter> <parameter> <name>url</name> <value>jdbc:mysql://localhost:3306/platform</value> </parameter> <parameter> <name>user</name> <value>root</value> </parameter> <parameter> <name>pwd</name> <value></value> </parameter> <parameter> <name>associateConnectionPool</name> <value>true</value> </parameter> <parameter> <name>connectionPoolName</name> <value>mysqlpool</value> </parameter> </DataSource> <ConnectionPoolConfig name="mysqlpool"> <parameter> <name>maxStatements</name> <value>20</value> </parameter> <parameter> <name>initialPoolSize</name> <value>10</value> </parameter> <parameter> <name>minPoolSize</name> <value>10</value> </parameter> <parameter> <name>maxPoolSize</name> <value>20</value> </parameter> <parameter> <name>maxidleTime</name> <value>3</value> </parameter> <parameter> <name>propertyCycle</name> <value>300</value> </parameter> </ConnectionPoolConfig> </Context>
调用代码
//The default datasource of Persistence2 framework is the first datasource in xml String defaultDataSourceName = MultiConnectionPool.getInstance().getDefaultDataSourceName(); //Get connection from connection pool of default datasource Connection conn1 = MultiConnectionPool.getInstance().getConnection(defaultDataSourceName); // Get connection from connection pool by datasource name Connection conn2 = MultiConnectionPool.getInstance().getConnection(“test”);
ORM规则的控制粒度是表级(或对象级),用于在表和对象之间建立映射关系,实现对单表数据的快速存取。其特点是配置简单,但表的字段和对象的属性的名称需一致,模式单一,适用于完整对象的存取。
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> >class>com.nonesole.web.platform.sys.User>/class> <table>sys_user </table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.Role>/class> <table>sys_role</table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.UserRole>/class> <table>sys_user_role</table> <primery-key/> </object> </object-sql-mapping> </config>
配置说明:
ORM-PLUS规则的控制粒度是字段级(或属性级),基于ORM规则基础上,用于在表字段和对象的属性之间建立映射关系,字段名与属性名需一致。该规则的特点是控制灵活,但配置复杂。
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUserById" transaction="true"> <orm-action>select</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.web.platform.sys.User </item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action> </actions> </config>
配置说明:
SQL-MAPPING规则的控制粒度是字段级(或属性级),与ORM-PLUS规则的最大不同之处在于,SQL-MAPPING规则在SQL字段和对象的属性之间建立映射关系,与表无关,字段名与属性名无需一致。该规则的特点是控制灵活,接口丰富,但配置复杂。
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUsersByAge" transaction="true"> <input> <object property="map"> <mapping> <source> <name>age</name> <class>int</class> <not-null>true</not-null> </source> <target> <name>//age</name> </target> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.web.platform.sys.User </item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user where age>//age</sql> </action> </actions> </config>
配置说明:(与ORM-PLUS重复的不再赘述)
保存整个对象的实现很简单,只需按照ORM规则设置好映射关系,调用过程由框架全权处理。
配置示例(如果无主键primery-key可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.User</class> <table>sys_users </table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User(); u.setName("tom"); …… IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action.insert(u); System.out.println(u.getId());
批量保存的配置与单个保存一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchInsert(users);
针对当前需求,最佳方案是依托 ORM-PLUS规则实现。
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="saveUser" transaction="true"> <orm-action>insert</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> <default-value/> <min-length>2</min-length> <max-length>20</max-length> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User(); u.setName("tom"); …… IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); action.doAction("saveUser", u); System.out.println(u.getId());
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="batchSaveUser" transaction="true"> <orm-action>insert</orm-action> <input> <object property="orm-pojo-list"> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> <min-length>2</min-length> <max-length>20</max-length> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
List<User> users = new ArrayList<User>(); users.add(…); IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); action.doAction("batchSaveUser ", users);
在某些特定场景下,开发者仅仅需要一个可调用SQL的方法,没有输入和输出。例如执行insert…select语句。
使用SQL-MAPPING实现
配置示例:
<config> <actions> <action name="createTempTable" transaction="true"> <input/> <output/> <sql>insert into temp(id,name) select id,name from user</sql> </action> </actions> </config>
代码示例:
IVoidAction action = PersistenceFactory.getInstance().getVoidAction(); action.doAction("createTempTable", null);
使用ORM实现
代码示例:
IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action.execute("insert into temp(id,name) select id,name from user");
当前需求场景,只需按照ORM规则设置好映射关系,调用过程由框架全权处理。需要注意的是,主键一定不能为空。
配置示例(主键primery-key不可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys. User</class> <table>sys_users</table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User(); u.setId(10); u.setName("tom"); …… IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action.update(u);
批量修改的配置与单个修改一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchUpdate(users);
通过ORM-PLUS规则来实现数据的修改,重点是where子句的配置。
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="updateUser" transaction="true"> <orm-action>update</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User(); u.setId(8); u.setName("tom"); IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); action.doAction("updateUser", u);
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="updateUser" transaction="true"> <input> <object property="map"> <mapping> <source> <name>id</name> <class>int</class> </source> <target> <name>//id</name> </target> </mapping> <mapping> <source> <name>name</name> <class>String</class> </source> <target> <name>//name</name> </target> </mapping> </object> </input> <output></output> <sql> update user set name=//name where id=//id and not exist (select 1 from (select 1 from user_role where user_id=//id) t1 ) </sql> </action> </actions> </config>
代码示例:
Map map = new HashMap(); map.put("id",10); map.put("name","tom"); …… IVoidAction action = PersistenceFactory.getInstance().getVoidAction(); action.doAction("updateUser ", map);
配置示例(主键primery-key不可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.user.User</class> <table>sys_users_login</table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User(); u.setId(10); …… IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action.delete(u);
批量删除的配置与单个对象的删除一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchDelete(users);
ORM-PLUS方法
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="deleteUser" transaction="true"> <orm-action>delete</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> <mapping> <source> <where>true</where> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User(); u.setName("tom"); …… IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); action.doAction("updateUser", u);
SQL-MAPPING方法
针对级联删除,框架提供了SQL-MAPPING规则来实现。
配置示例(针对级联删除操作这样需要执行多个SQL的场景,框架允许在一个Action中配置多个<sql>标签。):
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="deleteUser" transaction="true"> <input> <object property="map"> <mapping> <source> <name>id</name> <class>int</class> </source> <target> <name>//id</name> </target> </mapping> </object> </input> <output></output> <sql>delete from user_role where user_id=//id</sql> <sql>delete from user where id=//id </sql> </action> </actions> </config>
代码示例:
Map map = new HashMap(); map.put("id",10); …… IVoidAction action = PersistenceFactory.getInstance().getVoidAction(); action.doAction("updateUser ", map);
ORM方法
基于ORM规则的DQL与DML的持久化配置无差别,这里不再赘述。
代码示例:
IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); List<Object> users = action.execute("select * from user",User.class);
ORM-PLUS方法
配置示例:
<action name="findUsers" transaction="true"> <orm-action>select</orm-action> <input></input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action>
代码示例:
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); List<Object> users = action. doQueryAction ("findUsers ", new User());
SQL-MAPPING方法
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUsers" transaction="true"> <input></input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user</sql> </action> </actions> </config>
代码示例:
IPojoAction<User> action = PersistenceFactory.getInstance().getPojoAction(); List<User> users = action. pojoListAction ("findUsers", null);
ORM方法
此场景下,SQL中需要编入外部数据,如果使用ORM接口,就需要拼SQL,从安全的角度,不建议使用。
ORM-PLUS方法
配置示例:
<action name="findUsers" transaction="true"> <orm-action>select</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action>
代码示例:
User user = new User(); user.setAge(18); IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction(); List<User> users = action. doQueryAction ("findUsers ", user);
SQL-MAPPING方法
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>age</name> <class>int</class> <not-null>true</not-null> </source> <target> <name>//age</name> </target> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user where age=//age</sql> </action>
代码示例:
Map<String,Object> map = new HashMap<String,Object>(); map.put("age",18); IPojoAction<User> action = PersistenceFactory.getInstance().getPojoAction(); List<User> users = action. pojoListAction ("findUsers", map);
面对复杂的业务查询,框架提供了2种解决方案,从安全性角度来说,推荐使用预编译方案,带来的是配置和编码复杂度的提升。从易用性角度出发,非预编译方案更受欢迎。
预编译解决方案
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>start_index</name> <class>int</class> <not-null>true</not-null> <default-value>1</default-value> </source> <target> <name>//start_index</name> </target> </mapping> <mapping> <source> <name>condition</name> <class>java.lang.String</class> <not-null>false</not-null> </source> <target> <name>//condition</name> </target> <sql-part>true</sql-part> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>java.lang.String</class> </target> </mapping> </object> </output> <sql> select * from sys_users_login //condition order by id desc limit //start_index,10 </sql> </action>
配置说明:
1.依据SQL-MAPPING规则,框架先对SQL进行编译处理,再向SQL赋值。
2.以当前场景为例,动态拼接后的提交框架处理的数据如下:
//condition= where (name like //name// and nick_name like //name//)
//name//=%tom%
start_index=1
框架将先将//condition与<sql>标签中的内容拼成完整SQL,编译之后再将name和start_index的数据编入SQL,并执行。
代码示例:
Map<String,Object> map = new HashMap<String,Object>(); map.put("start_index ",1); map.put("//condition", "where (name like //name// and nick_name like //name//)"); map.put("//name//","%tom%"); IPojoAction<User> action = PersistenceFactory.getInstance().getPojoAction(); List<User> users = action. pojoListAction ("findUsers", map);
ORM方案(非预编译)
该方案无需配置,直接在代码中拼SQL即可,但返回值类型受限。
代码示例:
String sql = "select * from user where age > " + 18; IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); List<Object> users = action.execute(sql,User.class);
SQL-MAPPING方案(非预编译)
该方案的返回值类型可选,但还是要在代码中拼SQL,传入数据的安全性和正确性需要开发者自行保障。
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>condition</name> <class>java.lang.String</class> <not-null>false</not-null> </source> <target> <name>//condition</name> </target> </mapping> </object> </input> <output> <object property="simple-list"> <mapping> <source> <name>id</name> </source> <target> <class>int</class> </target> </mapping> </object> </output> <sql>select id from sys_users_login //condition order by id desc</sql> </action>
代码示例1:
Map<String,Object> map = new HashMap<String,Object>(); map.put("condition", "where age > 18"); Connection conn = PersistenceFactory.getInstance().getDefaultConnection(); IArrayValueAction action = PersistenceFactory.getInstance().getArrayValueAction(); //It is not prepared statement Integer[] id = action. intArrayAction ("findUser", map, conn, false);
代码示例2:
Map<String,Object> map = new HashMap<String,Object>(); map.put("condition", "where age > 18"); Connection conn = PersistenceFactory.getInstance().getDefaultConnection(); IListValueAction action = PersistenceFactory.getInstance().getListValueAction (); //It is not prepared statement List<Integer> id = action. intListAction ("findUser", map, conn, false);
配置示例:
<action name="deleteUser" transaction="true"> …… <sql>delete from user_role where user_id=//id</sql> <sql>delete from user where id=//id</sql> <sql>insert into log(…) values(…)</sql> </action>
代码示例:
Map<String,Object> map = new HashMap<String,Object>(); map.put("id", 10); …… IVoidAction action = PersistenceFactory.getInstance().getVoidAction(); action.doAction("deleteUser", map);
配置示例:
<action name="deleteUserRelation" transaction="false"> …… <sql>delete from user_role where user_id=//id</sql> </action> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.User</class> <table>sys_users </table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.Log</class> <table>sys_log</table> <primery-key>id</primery-key> </object> </object-sql-mapping>
代码示例:
PSession ps = new PSession(); Map<String,Object> map = new HashMap<String,Object>(); …… ps.voidAction("deleteUserRelation", map); User u = new User(); u.setId(10); ps.delete(u); Log log = new Log(); log.setText("error."); ps.insert(log); ps.commit();